/*
 ============================================================================
 Name        : fString.cpp
 Author      : 
 Version     :
 Copyright   : vivame
 Description : CfString implementation
 ============================================================================
 */

#include "TextConvert.h"
#include "f32file.h"
#include "e32test.h"

////////////////////////////////////////////////////////////////////////////////////
// fTextConverter

HBufC16* fTextConverter::ConvertToUnicode( const TDesC8& aBuffer, TCharSet aCharSet )
{
    RFs fsSession;
    User::LeaveIfError( fsSession.Connect( ) );
    CCnvCharacterSetConverter* pConvert = CCnvCharacterSetConverter::NewL( );
    if( !pConvert )
    {
        fsSession.Close( );
        return NULL;
    }
    CArrayFix< CCnvCharacterSetConverter::SCharacterSet >* pCharset = pConvert->CreateArrayOfCharacterSetsAvailableLC( fsSession );
    if( !pCharset )
    {
        fsSession.Close( );
        return NULL;
    }

    pConvert->PrepareToConvertToOrFromL( aCharSet, *pCharset, fsSession );
    HBufC16* pUnicode = HBufC16::NewL( aBuffer.Length( ) * 2 );
    if( !pUnicode )
    {
        return NULL;
    }

    TPtr16 unicodePtr = pUnicode->Des( );
    unicodePtr.FillZ( unicodePtr.MaxLength( ) );
    TPtrC8 leftText( aBuffer );
    int leftValue = -1;
    TInt state = CCnvCharacterSetConverter::KStateDefault;
    while( 1 )
    {
        leftValue = pConvert->ConvertToUnicode( unicodePtr, leftText, state );
        if( leftValue == 0 )
        {
            break;
        }
        else if( leftValue == CCnvCharacterSetConverter::EErrorIllFormedInput )
        {
            //User::Leave(KErrCorrupt);
            break;
        }
        else if( leftValue < 0 ) // future-proof against "TError" expanding
        {
            //User::Leave(KErrGeneral);
            break;
        }

        leftText.Set( leftText.Right( leftValue ) );
    }

    fsSession.Close( );
    delete pConvert;
    pConvert = NULL;
    CleanupStack::Pop( pCharset );
    delete pCharset;
    pCharset = NULL;
    if( leftValue == 0 )
    {
        HBufC16* pTemp = pUnicode->ReAlloc( pUnicode->Length( ) );
        if( pTemp )
        {
            return pTemp;
        }
        else
        {
            return pUnicode;
        }
    }
    else
    {
        delete pUnicode;
        return NULL;
    }
}

HBufC8* fTextConverter::ConvertFromUnicode( const TDesC16& aBuffer, TCharSet aCharSet )
{
    RFs fsSession;
    User::LeaveIfError( fsSession.Connect( ) );
    CCnvCharacterSetConverter* pConvert = CCnvCharacterSetConverter::NewL( );
    if( !pConvert )
    {
        fsSession.Close( );
        return NULL;
    }
    CArrayFix< CCnvCharacterSetConverter::SCharacterSet >* pCharset = pConvert->CreateArrayOfCharacterSetsAvailableLC( fsSession );
    if( !pCharset )
    {
        fsSession.Close( );
        return NULL;
    }

    pConvert->PrepareToConvertToOrFromL( aCharSet, *pCharset, fsSession );

    HBufC8* pOther = HBufC8::NewL( aBuffer.Length( ) * 2 );
    if( !pOther )
    {
        return NULL;
    }

    TPtr8 otherPtr = pOther->Des( );
    otherPtr.FillZ( otherPtr.MaxLength( ) );
    TPtrC16 leftText( aBuffer );
    int leftValue = -1;
    while( 1 )
    {
        leftValue = pConvert->ConvertFromUnicode( otherPtr, leftText );
        if( leftValue == 0 )
        {
            break;
        }
        else if( leftValue == CCnvCharacterSetConverter::EErrorIllFormedInput )
        {
            //User::Leave(KErrCorrupt);
            break;
        }
        else if( leftValue < 0 ) // future-proof against "TError" expanding
        {
            //User::Leave(KErrGeneral);
            break;
        }

        leftText.Set( leftText.Right( leftValue ) );
    }

    fsSession.Close( );
    delete pConvert;

    CleanupStack::Pop( pCharset );
    delete pCharset;
    pCharset = NULL;
    if( leftValue == 0 )
    {
        return pOther->ReAlloc( pOther->Length( ) );
    }
    else
    {
        delete pOther;
        return NULL;
    }
}

HBufC16* fTextConverter::ConvertToUnicode( char* szString, int nLength, TCharSet aCharSet )
{
    if( !szString )
    {
        return NULL;
    }

    if( nLength == -1 )
    {
        nLength = User::StringLength( ( unsigned char* )szString );
    }

    HBufC8* pTemp = HBufC8::NewL( nLength );
    if( !pTemp )
    {
        return NULL;
    }
    TPtr8 ptr = pTemp->Des( );
    ptr.Copy( ( unsigned char* )szString, nLength );

    HBufC16* pOut = fTextConverter::ConvertToUnicode( ptr, aCharSet );
    delete pTemp;
    return pOut;
}
